//-----------------------------------------------------------------------------
//  Copyright (c) 2013 by HangZhou HenqgQiao Design Corporation. All rights reserved.
//
//  Project  : 
//  Module   : 
//  Parent   : 
//  Children : 
//
//  Description: 
//
//  Parameters:
//  Local Parameters:
//
//  Notes       : 
//
//  Multicycle and False Paths

module AUPP_WRSYNC(
   input                                 GTM_AUPP_RESET,
   input                                 GTM_RX_CKOCK,
   input                                 GTM_SYS_CKOCK,
   // input write data from point analysis module.
   input[2:0]                            SYNC_IN_FFWR_CHNN,
   input                                 SYNC_IN_FFWR_AIS,
   input                                 SYNC_IN_FFWR_EN,
   input[7:0]                            SYNC_IN_FFWR_ADDR,

   output[2:0]                           SYNC_OUT_FFWR_CHNN,
   output                                SYNC_OUT_FFWR_AIS,
   output                                SYNC_OUT_FFWR_EN,
   output[7:0]                           SYNC_OUT_FFWR_ADDR
   );

reg[4:0]                                 SYNC_WRCNT;
reg[4:0]                                 SYNC_RDCNT;
reg[1:0]                                 SYNC_FSM;
wire[4:0]                                SYNC_FSM_WRCNT, SYNC_FSM_RDCNT;

wire                                     SYNC_RAM_CLKA, SYNC_RAM_CLKB;
wire                                     SYNC_RAM_WEA;
wire[4:0]                                SYNC_RAM_ADDRA, SYNC_RAM_ADDRB;
wire[11:0]                               SYNC_RAM_DINA, SYNC_RAM_DOUTB;

reg                                      SYNC_RDL_1_EN, SYNC_RDL_2_EN;


always @( posedge GTM_AUPP_RESET or posedge GTM_RX_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      SYNC_WRCNT[4:0]                               <= 5'd0;
   else begin
      if ( SYNC_IN_FFWR_EN==1'b1 )
         SYNC_WRCNT[4:0]                            <= SYNC_WRCNT[4:0] +5'd1;
   end
end

AUPP_FIFO_GRAY_5                         INST_GRAY_5(
   .GTM_AUPP_RESET                       ( GTM_AUPP_RESET ),
   .GTM_RX_CKOCK                         ( GTM_RX_CKOCK ),
   .GTM_SYS_CKOCK                        ( GTM_SYS_CKOCK ),
   // input write data from point analysis module.
   .SRC_IN_CNT                           ( SYNC_WRCNT[4:0] ),
   .DES_OUT_CNT                          ( SYNC_FSM_WRCNT[4:0] )
   );

// SYNC buffer read count, read the data in the buffer
always @( posedge GTM_AUPP_RESET or posedge GTM_SYS_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      SYNC_RDCNT[4:0]                               <= 5'd0;
   else begin
      if ( SYNC_FSM[1:0]==3'd3 )
         SYNC_RDCNT[4:0]                            <= SYNC_RDCNT[4:0] +5'd1;
   end
end
  assign SYNC_FSM_RDCNT[4:0]      = SYNC_RDCNT[4:0];

always @( posedge GTM_AUPP_RESET or posedge GTM_SYS_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      SYNC_FSM[1:0]                               <= 2'd0;
   else begin
      case ( SYNC_FSM[1:0] )
      2'd0: begin
         if ( SYNC_FSM_RDCNT[4:0]!=SYNC_FSM_WRCNT[4:0] )
            SYNC_FSM[1:0]                         <= 2'd1;
      end
      2'd1: SYNC_FSM[1:0]                         <= 2'd2;
      2'd2: SYNC_FSM[1:0]                         <= 2'd3;
      2'd3: begin
         if ( SYNC_FSM_RDCNT[4:0]==SYNC_FSM_WRCNT[4:0] )
            SYNC_FSM[1:0]                         <= 2'd0;
      end
      default: ;
      endcase
   end
end



  assign  SYNC_RAM_CLKA          = GTM_RX_CKOCK;
  assign  SYNC_RAM_WEA           = SYNC_IN_FFWR_EN;
  assign  SYNC_RAM_ADDRA[4:0]    = SYNC_WRCNT[4:0];
  assign  SYNC_RAM_DINA[7:0]     = SYNC_IN_FFWR_ADDR[7:0];
  assign  SYNC_RAM_DINA[10:8]    = SYNC_IN_FFWR_CHNN[2:0];
  assign  SYNC_RAM_DINA[11]      = SYNC_IN_FFWR_AIS;

  assign  SYNC_RAM_CLKB          = GTM_SYS_CKOCK;
  assign  SYNC_RAM_ADDRB[4:0]    = SYNC_RDCNT[4:0];
  assign  SYNC_OUT_FFWR_ADDR[7:0]= SYNC_RAM_DOUTB[7:0];
  assign  SYNC_OUT_FFWR_CHNN[2:0]= SYNC_RAM_DOUTB[10:8];
  assign  SYNC_OUT_FFWR_AIS      = SYNC_RAM_DOUTB[11];

AURG_WRSYNC_RAM384_12_12         INST_SYNC_RAM(
   .CLKA                         ( SYNC_RAM_CLKA ),
   .WEA                          ( SYNC_RAM_WEA ),
   .ADDRA                        ( SYNC_RAM_ADDRA[4:0] ),
   .DINA                         ( SYNC_RAM_DINA[11:0] ),

   .CLKB                         ( SYNC_RAM_CLKB ),
   .ADDRB                        ( SYNC_RAM_ADDRB[4:0] ),
   .DOUTB                        ( SYNC_RAM_DOUTB[11:0] )
   );


always @( posedge GTM_AUPP_RESET or posedge GTM_SYS_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 ) begin
      SYNC_RDL_1_EN                               <= 1'b0;
      SYNC_RDL_2_EN                               <= 1'b0;
   end
   else begin
      SYNC_RDL_1_EN                               <= SYNC_FSM[1:0]==2'd3;
      SYNC_RDL_2_EN                               <= SYNC_RDL_1_EN;
   end
end
  assign SYNC_OUT_FFWR_EN        = SYNC_RDL_2_EN;

endmodule













module AUPP_FIFO_GRAY_5(
   input                                 GTM_AUPP_RESET,
   input                                 GTM_RX_CKOCK,
   input                                 GTM_SYS_CKOCK,
   // input write data from point analysis module.
   input[4:0]                            SRC_IN_CNT,
   output reg[4:0]                       DES_OUT_CNT
   );

reg[4:0]                                 SRC_GRAY_CNT;
reg[4:0]                                 DES_GRAY_CNT;


always @( posedge GTM_AUPP_RESET or posedge GTM_RX_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      SRC_GRAY_CNT[4:0]                     <= 5'd0;
   else begin
      case (SRC_IN_CNT[4:0])
      5'h00: SRC_GRAY_CNT[4:0]              <= 5'b00000;
      5'h01: SRC_GRAY_CNT[4:0]              <= 5'b00001;
      5'h02: SRC_GRAY_CNT[4:0]              <= 5'b00011;
      5'h03: SRC_GRAY_CNT[4:0]              <= 5'b00010;
      5'h04: SRC_GRAY_CNT[4:0]              <= 5'b00110;
      5'h05: SRC_GRAY_CNT[4:0]              <= 5'b00111;
      5'h06: SRC_GRAY_CNT[4:0]              <= 5'b00101;
      5'h07: SRC_GRAY_CNT[4:0]              <= 5'b00100;
      5'h08: SRC_GRAY_CNT[4:0]              <= 5'b01100;
      5'h09: SRC_GRAY_CNT[4:0]              <= 5'b01101;
      5'h0A: SRC_GRAY_CNT[4:0]              <= 5'b01111;
      5'h0B: SRC_GRAY_CNT[4:0]              <= 5'b01110;
      5'h0C: SRC_GRAY_CNT[4:0]              <= 5'b01010;
      5'h0D: SRC_GRAY_CNT[4:0]              <= 5'b01011;
      5'h0E: SRC_GRAY_CNT[4:0]              <= 5'b01001;
      5'h0F: SRC_GRAY_CNT[4:0]              <= 5'b01000;
      5'h10: SRC_GRAY_CNT[4:0]              <= 5'b11000;
      5'h11: SRC_GRAY_CNT[4:0]              <= 5'b11001;
      5'h12: SRC_GRAY_CNT[4:0]              <= 5'b11011;
      5'h13: SRC_GRAY_CNT[4:0]              <= 5'b11010;
      5'h14: SRC_GRAY_CNT[4:0]              <= 5'b11110;
      5'h15: SRC_GRAY_CNT[4:0]              <= 5'b11111;
      5'h16: SRC_GRAY_CNT[4:0]              <= 5'b11101;
      5'h17: SRC_GRAY_CNT[4:0]              <= 5'b11100;
      5'h18: SRC_GRAY_CNT[4:0]              <= 5'b10100;
      5'h19: SRC_GRAY_CNT[4:0]              <= 5'b10101;
      5'h1A: SRC_GRAY_CNT[4:0]              <= 5'b10111;
      5'h1B: SRC_GRAY_CNT[4:0]              <= 5'b10110;
      5'h1C: SRC_GRAY_CNT[4:0]              <= 5'b10010;
      5'h1D: SRC_GRAY_CNT[4:0]              <= 5'b10011;
      5'h1E: SRC_GRAY_CNT[4:0]              <= 5'b10001;
      5'h1F: SRC_GRAY_CNT[4:0]              <= 5'b10000;
      default:;
      endcase
   end
end

always @( posedge GTM_AUPP_RESET or posedge GTM_SYS_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      DES_GRAY_CNT[4:0]                       <= 5'd0;
   else
      DES_GRAY_CNT[4:0]                       <= SRC_GRAY_CNT[4:0];
end

always @( posedge GTM_AUPP_RESET or posedge GTM_SYS_CKOCK ) begin
   if ( GTM_AUPP_RESET==1'b1 )
      DES_OUT_CNT[4:0]                        <= 5'd0;
   else begin
      case (DES_GRAY_CNT[4:0])
      5'b00000: DES_OUT_CNT[4:0]              <= 5'd0;
      5'b00001: DES_OUT_CNT[4:0]              <= 5'd1;
      5'b00011: DES_OUT_CNT[4:0]              <= 5'd2;
      5'b00010: DES_OUT_CNT[4:0]              <= 5'd3;
      5'b00110: DES_OUT_CNT[4:0]              <= 5'd4;
      5'b00111: DES_OUT_CNT[4:0]              <= 5'd5;
      5'b00101: DES_OUT_CNT[4:0]              <= 5'd6;
      5'b00100: DES_OUT_CNT[4:0]              <= 5'd7;
      5'b01100: DES_OUT_CNT[4:0]              <= 5'd8;
      5'b01101: DES_OUT_CNT[4:0]              <= 5'd9;
      5'b01111: DES_OUT_CNT[4:0]              <= 5'd10;
      5'b01110: DES_OUT_CNT[4:0]              <= 5'd11;
      5'b01010: DES_OUT_CNT[4:0]              <= 5'd12;
      5'b01011: DES_OUT_CNT[4:0]              <= 5'd13;
      5'b01001: DES_OUT_CNT[4:0]              <= 5'd14;
      5'b01000: DES_OUT_CNT[4:0]              <= 5'd15;
      5'b11000: DES_OUT_CNT[4:0]              <= 5'd16;
      5'b11001: DES_OUT_CNT[4:0]              <= 5'd17;
      5'b11011: DES_OUT_CNT[4:0]              <= 5'd18;
      5'b11010: DES_OUT_CNT[4:0]              <= 5'd19;
      5'b11110: DES_OUT_CNT[4:0]              <= 5'd20;
      5'b11111: DES_OUT_CNT[4:0]              <= 5'd21;
      5'b11101: DES_OUT_CNT[4:0]              <= 5'd22;
      5'b11100: DES_OUT_CNT[4:0]              <= 5'd23;
      5'b10100: DES_OUT_CNT[4:0]              <= 5'd24;
      5'b10101: DES_OUT_CNT[4:0]              <= 5'd25;
      5'b10111: DES_OUT_CNT[4:0]              <= 5'd26;
      5'b10110: DES_OUT_CNT[4:0]              <= 5'd27;
      5'b10010: DES_OUT_CNT[4:0]              <= 5'd28;
      5'b10011: DES_OUT_CNT[4:0]              <= 5'd29;
      5'b10001: DES_OUT_CNT[4:0]              <= 5'd30;
      5'b10000: DES_OUT_CNT[4:0]              <= 5'd31;
      default: ;
      endcase
   end
end

endmodule
